
// ts 泛型：泛型定义，泛型函数，泛型类，泛型接口等
export module GenericSyntax {
    // 定义：参数化类型，也可以看做是一种声明时不确定类型，使用时才确定类型的数据类型
    // 通俗点讲就是解决类、接口、方法的可复用性，以及对不特定数据类型的支持

    // #声明泛型方法，通常使用<T>声明泛型,使用什么字母不限制，但是要保证传入参数类型（any除外）和声明类型一致
    // 如果参数类型声明为any类型就没什么意义了
    // 限定返回类型为泛型类型
    // function getValue<T>(value: T): T {
    //     console.log(value);
    //     return value;
    // }
    // getValue<number>(123 + 123);
    // getValue<string>('123' + '123');

    // 返回类型不限定
    // function getValue<T>(value: T): any {
    //     return value + '123';
    // }
    // console.log(getValue<number>(123));
    // console.log(getValue<string>('123'));    


    // #泛型类
    // 取最小值，使用泛型
    // class GetMinValue<T> {
    //     list: T[] = [];
    //     add(num: T): void {
    //         this.list.push(num);
    //     }
    //     min(): T {
    //         let minNum = this.list.length ? this.list[0] : <any>0;
    //         for (let item of this.list) {
    //             if (item < minNum)
    //                 minNum = item;
    //         }
    //         return minNum;
    //     }
    // }
    // let mina = new GetMinValue<number>();
    // mina.add(9)
    // mina.add(3)
    // mina.add(6)
    // console.log(mina.min());
    // // 可复用
    // let min = new GetMinValue<string>();
    // min.add('2')
    // min.add('4')
    // min.add('6')
    // console.log(min.min());

    // 不使用泛型，取最小值，无法复用
    // class GetMinValue {
    //     list: number[] = [];
    //     add(num: number) {
    //         this.list.push(num);
    //     }
    //     min(): number {
    //         let minNum = this.list.length ? this.list[0] : 0;
    //         for (let item of this.list) {
    //             if (item < minNum)
    //                 minNum = item;
    //         }
    //         return minNum;
    //     }
    // }
    // let min = new GetMinValue();
    // min.add(2)
    // min.add(4)
    // min.add(6)
    // console.log(min.min());


    // #泛型接口
    // 定义泛型接口方式1
    // interface Options{
    //     <T>(value:T):T;
    // }

    // let getData=function <T>(params:T):T {
    //     return params
    // }
    // console.log(getData<string>('花生汤圆'));    

    // 定义泛型接口方式2
    // interface Options<T> {
    //     (value: T): T;
    // }

    // function getData<T>(params: T): T {
    //     return params
    // }
    // let myGetData: Options<string> = getData
    // let myGetNum: Options<number> = getData
    // console.log(myGetData('花生汤圆'));
    // console.log(myGetNum(369));

    // #泛型类，把类作为参数类型的泛型类

    // 未使用泛型的情况，每增加一种类型，就要定义一种特定类型的add方法，造成代码冗余
    // class User {
    //     username: string | undefined;
    //     password: string | undefined;
    // }
    // class Article {
    //     title: string | undefined;
    //     desc: string | undefined;
    // }
    // class MysqlDb {
    //     addUser(user: User): boolean {
    //         return true
    //     }
    //     addArticle(art: Article): boolean {
    //         return true
    //     }
    // }
    // let u=new User();
    // u.username='张小三'
    // u.password='888'
    // let a=new Article();
    // a.title='标题'
    // a.desc='内容'
    // let db=new MysqlDb();
    // console.log(db.addUser(u));
    // console.log(db.addArticle(a));
    
    // 使用泛型类优化上面的代码
    class User {
        username: string | undefined;
        password: string | undefined;
    }
    class Article {
        title: string | undefined;
        desc: string | undefined;
    }
    class MysqlDb<T>{
        add(info: T): boolean {
            console.log(info);            
            return true
        }

    }
    let u=new User();
    u.username='张小三'
    u.password='888'
    let a=new Article();
    a.title='标题'
    a.desc='内容'
    // 实例化时使用类类型对add数据进行约束
    let udb=new MysqlDb<User>();
    console.log(udb.add(u));
    let adb=new MysqlDb<Article>();
    console.log(adb.add(a));


}



